home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / PATHNAME.C < prev    next >
C/C++ Source or Header  |  1989-12-16  |  4KB  |  134 lines

  1. #include "global.h"
  2. #include <ctype.h>
  3.  
  4. /* Given a working directory and an arbitrary pathname, resolve them into
  5.  * an absolute pathname. Memory is allocated for the result, which
  6.  * the caller must free
  7.  */
  8. char *
  9. pathname(cd,path)
  10. char *cd;    /* Current working directory */
  11. char *path;    /* Pathname argument */
  12. {
  13.     register char *buf,*cp;
  14.     char *cdtmp,*pathtmp,*strcpy();
  15.  
  16.     if(cd == NULLCHAR || path == NULLCHAR)
  17.         return NULLCHAR;
  18.  
  19. #if    (defined(MSDOS) || defined(ATARI_ST))
  20.     /* Make temporary copies of cd and path
  21.      * with all \'s translated to /'s
  22.      */
  23.     if ((pathtmp = malloc((unsigned)strlen(path)+1)) == NULLCHAR)
  24.         return NULLCHAR;
  25.     for (cp = path = strcpy(pathtmp,path); *cp != '\0'; cp++)
  26.         if (*cp == '\\')
  27.             *cp = '/';
  28.  
  29.     if ((cdtmp = malloc((unsigned)strlen(cd)+1)) == NULLCHAR) {
  30.         free(pathtmp);
  31.         return NULLCHAR;
  32.     }
  33.     for (cp = cd = strcpy(cdtmp,cd); *cp != '\0'; cp++)
  34.         if (*cp == '\\')
  35.             *cp = '/';
  36. #endif
  37.  
  38.     /* Strip any leading white space on args */
  39.     while(*cd == ' ' || *cd == '\t')
  40.         cd++;
  41.     while(*path == ' ' || *path == '\t')
  42.         path++;
  43.  
  44.     /* Allocate and initialize output buffer; user must free */
  45.     buf = malloc((unsigned)strlen(cd) + strlen(path) + 10); /* fudge factor */
  46.     if (buf == NULLCHAR)
  47.         goto nomem;
  48.     buf[0] = '\0';
  49.  
  50.     /* Interpret path relative to cd only if it doesn't begin with "/" */
  51.     /* or "D:/" (support for drive names) */
  52.     if(path[0] == '/' && cd[1] == ':') {
  53.         buf[0] = cd[0];        /* start from root on current drv */
  54.         buf[1] = ':';
  55.         buf[2] = '\0';
  56.     }
  57.     if(path[0] != '/' &&
  58.        !(isalpha(path[0]) && path[1] == ':' && path[2] == '/'))
  59.         crunch(buf,cd);
  60.  
  61.     crunch(buf,path);
  62.  
  63.     /* Special case: null final path or drive only means the root directory */
  64.     if(buf[0] == '\0' ||
  65.        (isalpha(buf[0]) && buf[1] == ':' && buf[2] == '\0'))
  66.         strcat(buf,"/");
  67.  
  68. nomem:
  69. #if    (defined(MSDOS) || defined(ATARI_ST))
  70.     /* Translate all /'s back to \'s and free temp copies of args */
  71.     for (cp = buf; *cp != '\0'; cp++)
  72.         if (*cp == '/')
  73.             *cp = '\\';
  74.     free(cdtmp);
  75.     free(pathtmp);
  76. #endif
  77.     return buf;
  78. }
  79.  
  80. /* Process a path name string, starting with and adding to
  81.  * the existing buffer
  82.  */
  83. static
  84. crunch(buf,path)
  85. char *buf;
  86. register char *path;
  87. {
  88.     register char *cp;
  89.  
  90.     if (isalpha(*path) && path[1] == ':'){ /* drive spec */
  91.         cp = buf;        /* Re-write entire buffer */
  92.         *cp++ = *path++;
  93.         *cp++ = *path++;
  94.         *cp = '\0';
  95.     } else {
  96.         cp = buf + strlen(buf); /* Start write at end of current buffer */
  97.     }
  98.  
  99.     /* Now start crunching the pathname argument */
  100.     for(;;){
  101.         /* Strip leading /'s; one will be written later */
  102.         while(*path == '/')
  103.             path++;
  104.         if(*path == '\0')
  105.             break;        /* no more, all done */
  106.         /* Look for parent directory references, either at the end
  107.          * of the path or imbedded in it
  108.          */
  109.         if(strcmp(path,"..") == 0 || strncmp(path,"../",3) == 0){
  110.             /* Hop up a level */
  111.             if((cp = rindex(buf,'/')) == NULLCHAR)
  112.                 cp = buf;    /* Don't back up beyond root */
  113.             *cp = '\0';        /* In case there's another .. */
  114.             path += 2;        /* Skip ".." */
  115.             while(*path == '/')    /* Skip one or more slashes */
  116.                 path++;
  117.         /* Look for current directory references, either at the end
  118.          * of the path or imbedded in it
  119.          */
  120.         } else if(strcmp(path,".") == 0 || strncmp(path,"./",2) == 0){
  121.             /* "no op" */
  122.             path++;            /* Skip "." */
  123.             while(*path == '/')    /* Skip one or more slashes */
  124.                 path++;
  125.         } else {
  126.             /* Ordinary name, copy up to next '/' or end of path */
  127.             *cp++ = '/';
  128.             while(*path != '/' && *path != '\0')
  129.                 *cp++ = *path++;
  130.         }
  131.     }
  132.     *cp++ = '\0';
  133. }
  134.